#include "Server.hpp"
#include <memory>
#include <unordered_map>
#include <fstream>
#include <signal.h>
#include "onlineUser.hpp"

using namespace std;
using namespace Server;

const string dictText = "./dict.txt"; // 字典
unordered_map<string, string> _dict;

static void Usage(string proc)
{
    cout << "\nUsage:\n\t" << proc << " local_port\n\n"; // 端口号
}

// static bool cutString(const string &target, string *key, string *value, const string &step)
// {
//     // apple:苹果
//     auto pos = target.find(step);
//     if (pos == string::npos)
//     {
//         return false;
//     }
//     // 采用截取字串的方式
//     *key = target.substr(0, pos);              // pos len -> [)
//     *value = target.substr(pos + step.size()); // 分割字符可能不同
//     return true;
// }

// // 将字典中的数据插入map中
// static void InitDict()
// {
//     ifstream in(dictText, std::ios_base::binary); // 二进制方式打开
//     if (!in.is_open())
//     {
//         // 打开失败
//         cerr << "open file " << dictText << " error " << endl;
//         exit(OPEN_ERR);
//     }
//     string line; // 将一行获取到这里
//     string key, value;
//     while (getline(in, line)) // 返回值会隐式类型转换
//     {
//         // 对字符串进行切割
//         if (cutString(line, &key, &value, ":"))
//         {
//             _dict.insert(make_pair(key, value));
//         }
//     }
//     in.close();
// }

// static void debugPrint()
// {
//     for (const auto &dict : _dict)
//     {
//         cout << dict.first << ":" << dict.second << endl;
//     }
// }

// demo1
// void handlerMessage(int sockfd, uint16_t port, string ip, string message)
// {
//     // 对message进行处理 apple
//     string respond_Message;
//     auto iter = _dict.find(message);
//     if (iter == _dict.end())
//     {
//         // 找不到
//         respond_Message = "Unknown";
//     }
//     else
//     {
//         respond_Message = iter->second;
//     }

//     // 将数据发送回客户端
//     struct sockaddr_in client;
//     bzero(&client, sizeof(client));
//     client.sin_port = htons(port);                  // 转换成网络
//     client.sin_addr.s_addr = inet_addr(ip.c_str()); // 转uint32_t 再转网络
//     client.sin_family = AF_INET;                    // 协议家族 UDP协议

//     sendto(sockfd, respond_Message.c_str(), respond_Message.size(), 0, (struct sockaddr *)&client, sizeof(client));
// }

// demo2  命令行解析
//  void execCommand(int sockfd,uint16_t clientPort,string clientIP,string cmd)
//  {
//      string responese;//返回的数据
//      FILE* fp = popen(cmd.c_str(),"r");
//      if(fp == nullptr)
//      {
//          responese +=" popen fail ";
//      }
//      else
//      {
//          char line[1024];
//          while(fgets(line,sizeof(line),fp))
//          {
//              responese +=line;
//          }
//      }

//     //将数据发送回客户端
//     struct sockaddr_in client;
//     bzero(&client,sizeof(client));
//     client.sin_family = AF_INET;
//     client.sin_port = htons(clientPort);
//     client.sin_addr.s_addr = inet_addr(clientIP.c_str());// 32 -> 网络

//     sendto(sockfd,responese.c_str(),responese.size(),0,(struct sockaddr*)&client,sizeof(client));
// }

// void reload(int signo)
// {
//     //void(signo);
//     InitDict();
// }

onlineUser _onlineUser; // 全局对象  聊天室

// demo3 广播消息
void routeMessage(int sockfd, uint16_t clientPort, string clientIP, string message)
{
    if (message == "online")
    {
        // 上线
        _onlineUser.addUsers(clientIP, clientPort);
    }
    if (message == "offline")
    {
        // 下线
        _onlineUser.deleteUsers(clientIP, clientPort);
    }
    if (_onlineUser.is_onlineUsers(clientIP, clientPort))
    {
        // 如果在线，就发送消息给聊天室中的成员
        _onlineUser.broadCast(sockfd, clientPort, clientIP, message);
    }
    else
    {
        // 没有在线，就发送提示给客户端，说请上线
        struct sockaddr_in client;
        bzero(&client, sizeof(client));
        client.sin_family = AF_INET;
        client.sin_port = htons(clientPort);
        client.sin_addr.s_addr = inet_addr(clientIP.c_str()); // 32 -> 网络

        string responese = "你还没有上线,请发送 online ,才能与聊天室中成员聊天!";

        sendto(sockfd, responese.c_str(), responese.size(), 0, (struct sockaddr *)&client, sizeof(client));
    }
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        // 设置退出码
        exit(USAGE_ERR);
    }
    // 端口号是一个uint6_t的整数
    uint16_t port = atoi(argv[1]);
    // debugPrint();

    // 采取接受信号的方式reload字典
    // signal(2,reload);
    // InitDict(); // 加载字典

    // unique_ptr<UdpServer> usvr(new UdpServer(handlerMessage, port));
    // unique_ptr<UdpServer> usvr(new UdpServer(execCommand, port));

    unique_ptr<UdpServer> usvr(new UdpServer(routeMessage, port));
    usvr->InitServer();
    usvr->StartServer();
    return 0;
}
